﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EPiServer.Web.Hosting;
using Microsoft.WindowsAzure.StorageClient;
using EPiServer.Security;
using System.Web;
using System.Web.Hosting;

namespace DBLOG.Azure.VirtualPathProvider.Entities
{
    public class CloudDirectory : UnifiedDirectory
    {
        public string ContainerName { get; set; }

        public override AccessControlList ACL
        {
            get
            {
                // TODO: Debug purposes only!
                var acl = new AccessControlList();
                if (BypassAccessCheck)
                {
                    acl.Add(new AccessControlEntry("Everyone", AccessLevel.FullAccess, SecurityEntityType.Role));
                }
                return acl;
            }
        }

        public CloudDirectory(VirtualPathUnifiedProvider provider, string virtualPath, string customSummary, bool byPassAccessCheck, string containerName) :
            base(provider, virtualPath, customSummary, byPassAccessCheck)
        {
            this.ContainerName = containerName;
        }

        public override UnifiedFile CreateFile(string name)
        {
            return CreateFile(name, Guid.NewGuid());
        }

        public override UnifiedFile CreateFile(string name, Guid id)
        {
            if (this.QueryDistinctAccess(AccessLevel.Create) == false)
                throw new UnauthorizedAccessException("You are not authorized to create files under " + VirtualPath);

            string path = Provider.CombineVirtualPaths(VirtualPath, name);

            UnifiedVirtualPathEventArgs e = new UnifiedVirtualPathEventArgs(path, null);
            this.OnFileAdded(e);

            if (e.Cancel)
            {
                throw new InvalidOperationException("The operation has been cancelled with the following reason: " + e.Reason);
            }

            CloudBlob blob = BlobStorageDataFactory.Instance.CreateFile(this, path, this.ContainerName);

            return new CloudFile(this, this.Provider, path, true, this.ContainerName);
        }

        public override void Delete()
        {
            base.Delete();
        }

        public override UnifiedDirectory CreateSubdirectory(string path)
        {
            string fullPath = VirtualPathUtility.Combine(this.VirtualPath, path);

            BlobStorageDataFactory.Instance.CreateDirectory(fullPath, this.ContainerName);

            return new CloudDirectory(this.Provider, fullPath, String.Empty, true, this.ContainerName);
        }

        public override UnifiedDirectory[] GetDirectories()
        {
            return Directories
                .Cast<CloudDirectory>()
                .ToArray();
        }

        public override System.Collections.IEnumerable Children
        {
            get
            {
                var list = Directories.Cast<object>().ToList();

                list.AddRange(Files.Cast<object>());

                return list;
            }
        }

        public override System.Collections.IEnumerable Directories
        {
            get
            {
                List<CloudDirectory> directories = new List<CloudDirectory>();

                List<CloudBlobDirectory> cloudDirectories = BlobStorageDataFactory.Instance.GetDirectories(this.VirtualPath, this.ContainerName);

                foreach (CloudBlobDirectory cloudDirectory in cloudDirectories)
                {
                    directories.Add(new CloudDirectory(this.Provider, cloudDirectory.Uri.AbsolutePath, String.Empty, false, this.ContainerName));
                }

                return directories;
            }
        }

        public override System.Collections.IEnumerable Files
        {
            get
            {
                var files = new List<CloudFile>();

                List<CloudBlob> blobs = BlobStorageDataFactory.Instance.GetFiles(this.VirtualPath, this.ContainerName);

                foreach (CloudBlob blob in blobs)
                {
                    string fileName = VirtualPathUtility.GetFileName(blob.Uri.ToString());

                    string path = VirtualPathUtility.Combine(this.VirtualPath, fileName);

                    files.Add(new CloudFile(this, this.Provider, path, true, this.ContainerName));
                }

                return files;
            }
        }

        public override UnifiedDirectory Parent
        {
            get
            {
                string parentDirectoryPath = VirtualPathUtility.GetDirectory(this.VirtualPath);

                CloudDirectory parentDirectory = Provider.GetDirectory(parentDirectoryPath) as CloudDirectory;

                return parentDirectory;
            }
        }

        public override bool IsVersioningSupported
        {
            get
            {
                return false;
            }
        }

        public override bool IsFirstLevel
        {
            get
            {
                return (Parent == null);
            }
        }

        public override UnifiedFile[] GetFiles()
        {
            List<CloudFile> files = new List<CloudFile>();

            List<CloudBlob> items = BlobStorageDataFactory.Instance.GetFiles(this.VirtualPath, this.ContainerName);

            foreach (CloudBlob item in items)
            {
                string fileName = VirtualPathUtility.GetFileName(item.Uri.AbsolutePath);

                // Do not return the dummy file needed to maintain the blob storage virtual directory
                if (!fileName.Equals(BlobStorageDataFactory.CLOUD_PROVIDER_DUMMY_FILE_NAME))
                {
                    string virtualPath = this.VirtualPath + fileName;

                    files.Add(new CloudFile(this, this.Provider, virtualPath, true, this.ContainerName));
                }
            }

            return files.ToArray();
        }

        public override string Name
        {
            get
            {
                return HttpUtility.UrlDecode(base.Name);
            }
        }
    }
}
